/**************************************************************************
* This file is part of Hawkengine.
*
* Hawkengine is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Hawkengine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Hawkengine.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#ifndef _COMMON_H_
#define _COMMON_H_

/**************************************************************************
* Dependencies
**************************************************************************/
#include "host.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
 
/**************************************************************************
* Preprocessing
**************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif

#ifndef BOOL
#define BOOL int
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef UCHAR
#define UCHAR unsigned char
#endif
#ifndef USHORT
#define USHORT unsigned short
#endif
#ifndef UINT
#define UINT unsigned int
#endif
#ifndef ULONG
#define ULONG unsigned long
#endif
 
#define MAX_DEBUGGING_LEVEL 3

#define EPSILON 0.0001
#define PI 3.141592653589793
#define MAX_DATE_LENGTH 32
#define MAX_PATH_LENGTH 512

#define DEG_PER_RAD (180.0 / PI)
#define RAD_PER_DEG (PI / 180.0)
#define HALF_PI (PI / 2.0)

#define _ADD(x, a, max) x = _MIN(x + a, max)
#define _BETWEEN(x, a, b) ((x >= a) && (x <= b))
#define _CLOSE_ENOUGH(x, y) _BETWEEN(x, (y - EPSILON), (y + EPSILON))
#define _CONCAT(start, end) _CONCAT_INTERMEDIATE(start, end)
#define _CONCAT_INTERMEDIATE(start, end) start##end
#define _LIMIT(x, a, b) _MAX(a, _MIN(x, b))
#define _MATRIX_ENTRY(m, cols, x, y) m[(y * cols) + x] // row major
#define _MAX(a, b) ((a > b) ? a : b)
#define _MIN(a, b) ((a < b) ? a : b)
#define _QUOTE(x) _QUOTE_INTERMEDIATE(x)
#define _QUOTE_INTERMEDIATE(x) #x
#define _SUBTRACT(x, a, min) x = _MAX(x - a, min)
#define _TOGGLE(x) x = !(x)
#define _UPDATE_MIN(x, a) x = _MIN(x, a)
#define _UPDATE_MAX(x, a) x = _MAX(x, a)

enum {
  X,
  Y,
  Z
};

#define MAX_TOUCHES 4
#define SHORT_CLICK_DELAY 0.5
#define MED_CLICK_DELAY 1.0
#define LONG_CLICK_DELAY 2.0

#define UNUSED_PARAM(x) (void)x

/**************************************************************************
* Types
**************************************************************************/
typedef float loc_type[2];
typedef struct
{
  loc_type loc;
  float rot;
} position_type;

typedef struct
{
  float velocity[2];
  float vrot;
} motion_type;

typedef enum
{
  FORWARD,
  BACK,
  LEFT,
  RIGHT,
  DOWN,
  UP,
  NAVIGATION_COUNT,
} navigation_type;

typedef struct
{
  UINT count;
  loc_type locs[MAX_TOUCHES];
  loc_type delta[MAX_TOUCHES];
} touch_type;

typedef struct
{
  float pos[3];
  float focus[3];
  float up[3];
} camera_type;

typedef struct
{
  const char* name;
  const char* extension;
  UINT size;
  const UCHAR* data;
} file_data_type;

typedef enum
{
  LOG_LEVEL_CRITICAL,
  LOG_LEVEL_ERROR,
  LOG_LEVEL_WARNING,
  LOG_LEVEL_INFO,
  LOG_LEVEL_DEBUG,
  LOG_LEVEL_COUNT,
} log_level_type;

/**************************************************************************
* Variables
**************************************************************************/
extern BOOL IS_LITTLE_ENDIAN;
extern const char* APP_ABOUT;
extern const char* APP_COPYRIGHT;
extern const char* APP_TITLE;
extern const char* PATH_SEPARATOR;
extern const float UPDATE_SECS;
extern UCHAR debugging_level;
extern log_level_type level_logged;
extern const camera_type DEFAULT_CAMERA;

/**************************************************************************
* Static Variables
**************************************************************************/

/**************************************************************************
* Function Prototypes
**************************************************************************/
void common_init(void);
void common_uninit(void);
void current_date(char* buffer);
UINT current_time_seconds(void);
float elapsed_seconds(void);
void format_time(UINT time, const char* format, char* buffer);
void get_data_dir(char* dir);
void get_resource_dir(char* dir);
void log_message(log_level_type log_level, const char* message, ...);
void log_read(char* buffer, int buffer_size, int start_idx);
int log_size(void);
void set_data_dir(const char* dir);
void set_resource_dir(const char* dir);

/**************************************************************************
* Function Implementations
**************************************************************************/


#ifdef __cplusplus
}
#endif

#endif

